from io import BytesIO
import uuid
import datetime

from django.shortcuts import render, redirect, HttpResponse
from django.http import JsonResponse
from django.core.cache import cache

from app01.utils.form.account_form import RegisterModelForm, LoginForm, SendMailRegisterForm, ForgotPasswordModelForm, SendMailForgotPassword
from app01 import models
from app01.utils.code import check_code
from app01.utils.code_smtp import send_verification_code

def send_email_code_register(request):
    """ 发送验证码(注册) """
    form = SendMailRegisterForm(data=request.GET)
    if form.is_valid():
        usermail = str(request.GET.get('usermail', '')).strip().lower()

        print(f"准备发送验证码到: {usermail}")
        
        code = send_verification_code(email_receiver=usermail)
        if code:
            print(f"生成的验证码是: {code}")

        # 使用一致的键名前缀
        redis_key = f'verify:{usermail}'
        
        # 使用Django缓存API更安全
        cache.set(redis_key, str(code), timeout=300)
        
        # 或者使用原生Redis连接
        # conn = get_redis_connection("default")
        # conn.setex(redis_key, 300, str(code))
        
        return JsonResponse({
            'status': True,
            'message': '验证码已发送',
            'email': usermail
        })
    
    return JsonResponse({
        'status': False,
        'message': '账户已经存在',
    })

def send_email_code_forget(request):
    """ 发送验证码(忘记密码) """
    form = SendMailForgotPassword(data=request.GET)
    if form.is_valid():
        usermail = str(request.GET.get('usermail', '')).strip().lower()

        print(f"准备发送验证码到: {usermail}")
        
        code = send_verification_code(email_receiver=usermail)
        if code == None:
            return JsonResponse({
                'status': False,
                'message': '网络异常',
            })
        else:
            print(f"生成的验证码是: {code}")
            # 使用一致的键名前缀
            redis_key = f'verify:{usermail}'
            
            # 使用Django缓存API更安全
            cache.set(redis_key, str(code), timeout=300)
            
            return JsonResponse({
                'status': True,
                'message': '验证码已发送',
                'email': usermail
            })
        
    return JsonResponse({
        'status': False,
        'message': '账户不存在',
    })


def register(request):
    """ 用户注册 """

    # GET 请求, 打开页面
    if request.method == "GET":
        form = RegisterModelForm()
        return render(request, "account\\register.html", {"form": form})
    
    # POST 请求, 注册数据校验
    form = RegisterModelForm(data=request.POST)

    if form.is_valid():
        # 通过数据效验, 写入数据库
        # 自动剔除无效数据, 赋值新数据与于instance
        instance = form.save()

        # 创建交易记录
        # 处理价格策略, 方式1: 对应middleware//auth//方式一
        policy_object = models.PricePolicy.objects.filter(category=1).first()
        if not policy_object:
            policy_object = models.PricePolicy.objects.create(
                category=1,
                title="个人免费版",
                price=0,
                project_num = 3,
                project_member = 2,
                project_space = 20,
                project_size = 5,
            )
        models.Transaction.objects.create(
            status=1,
            order=str(uuid.uuid4()),
            user=instance,
            price_policy=policy_object,
            count=0,
            price=0,
            start_datetime=datetime.datetime.now(),
        )
        # 处理价格策略(不用写), 方式2: 对应middleware//auth//方式二

        return JsonResponse({
            'status': True,
            'data': '/login/'
        })
    
    return JsonResponse({
        "status": False,
        'error': form.errors,
    })

def login(request):
    """ 登录 """

    if request.method == "GET":
        form = LoginForm()
        return render(request, "account\\login.html", {"form":form})
    
    form = LoginForm(data=request.POST)

    if form.is_valid():

        # 验证码效验
        user_input_code = form.cleaned_data.pop('code')
        code = request.session.get('image_code', "")
        if code.upper() != user_input_code.upper():
            form.add_error("code","验证码错误")
            return render(request, 'account\\login.html', {"form": form})
        
        # 登录数据效验
        user_object = models.User.objects.filter(**form.cleaned_data).first()
        if not user_object:
            form.add_error("password","用户名或密码错误")
            return render(request,'account\\login.html',{"form":form})
        
        # 验证成功,写入用户浏览器cookie与session

        # 获取是否勾选"记住我"
        remember_me = request.POST.get('remember-me',"")  

        request.session['info'] = {'id': user_object.id,'name':user_object.usermail}

        if remember_me:
            #设置session保存时间,30天 = 60s * 60min * 24h * 30天
            request.session.set_expiry(60 * 60 * 24 * 30)
        else:
            # 浏览器关闭时失效
            request.session.set_expiry(0)  

        return redirect('/index/')


    return render(request, "account\\login.html", {"form":form})

def forget_password(request):
    
    if request.method == "GET":
        form = ForgotPasswordModelForm()
        return render(request, "account\\forgot.html", {"form": form})
    """ instance 的主要作用是： 
        1. ​预填充表单数据：将模型实例的数据加载到表单中。 
        2. ​更新记录：在保存表单时，更新绑定的模型实例。 
        3. ​区分创建和编辑：通过是否提供 instance 来决定是创建新记录还是编辑现有记录。  
        如果没有提供 instance，表单会用于创建新记录，调用 form.save() 时会插入一条新数据。 
        """
    # 获取编辑行对象
    row_object = models.User.objects.filter(usermail=request.POST.get('usermail')).first()
    form = ForgotPasswordModelForm(data=request.POST,instance=row_object)

    if form.is_valid():
        # 通过数据效验, 写入数据库
        # 自动剔除无效数据
        
        form.save()
        return JsonResponse({
            'status': True,
            'data': '/login/'
        })
    
    return JsonResponse({
        "status": False,
        'error': form.errors,
    })
    

def image_code(request):
    """ 生成图片验证码 """
    # 调用pillow函数，生成图片
    img, code_string = check_code()

    # 写入到自己的session中（以便于后续获取验证码再进行校验）
    request.session['image_code'] = code_string

    # 给Session设置60s超时
    request.session.set_expiry(60)
    stream = BytesIO()
    img.save(stream, 'png')
    return HttpResponse(stream.getvalue())

def logout(request):
    """ 注销登录 """
    request.session.clear()

    return redirect('/login/')